home *** CD-ROM | disk | FTP | other *** search
/ Moving Worlds - Companion / Moving Worlds.iso / obj2wrl / obj2wrl < prev    next >
Text File  |  1995-06-22  |  15KB  |  526 lines

  1. #!/usr/local/apps/perl/bin/perl
  2. #############################################################################
  3. #                                                                           #
  4. #  WHO:    John L. Moreland                                                 #
  5. #                                                                           #
  6. #  WHAT:   obj2wrl                                                          #
  7. #                                                                           #
  8. #  WHY:    Converts a wavefront OBJ file to a VRML file.                    #
  9. #                                                                           #
  10. #  WHERE:  San Diego Supercomputer Center (SDSC)                            #
  11. #                                                                           #
  12. #  WHEN:   Wed Mar 15 13:00:23 PST 1995  (ORIGINAL)                         #
  13. #          Tue Apr 11 10:15:36 PST 1995  (CURRENT)                          #
  14. #                                                                           #
  15. #  HOW:    Perl                                                             #
  16. #                                                                           #
  17. #############################################################################
  18. #                                                                           #
  19. #  Copyright (c) 1995  San Diego Supercomputer Center (SDSC)                #
  20. #       a division of General Atomics, San Diego, California, USA           #
  21. #                                                                           #
  22. #       Users and possessors of this source code are hereby granted a       #
  23. #       nonexclusive, royalty-free copyright and design patent license to   #
  24. #       use this code in individual software.  License is not granted for   #
  25. #       commercial resale, in whole or in part, without prior written       #
  26. #       permission from SDSC.  This source is provided "AS IS" without      #
  27. #       express or implied warranty of any kind.                            #
  28. #                                                                           #
  29. #       For further information contact:                                    #
  30. #               E-Mail:         info@sds.sdsc.edu                           #
  31. #                                                                           #
  32. #               Surface Mail:   Information Center                          #
  33. #                               San Diego Supercomputer Center              #
  34. #                               P.O. Box 85608                              #
  35. #                               San Diego, CA  92138-5608                   #
  36. #                               (619) 534-5000                              #
  37. #                                                                           #
  38. #############################################################################
  39.  
  40.  
  41. #############################################################################
  42. ################################  SUBROUTINES  ##############################
  43. #############################################################################
  44.  
  45.  
  46. #############################################################################
  47. #                                                                           #
  48. #  Returns the maximum of all values passed in.                             #
  49. #                                                                           #
  50. #############################################################################
  51. sub max
  52. {
  53.     local( $result ) = pop( @_ );
  54.     foreach $item ( @_ )
  55.     {
  56.         $result = $item if $item > $result;
  57.     }
  58.     return( $result );
  59. }
  60.  
  61.  
  62. #############################################################################
  63. #                                                                           #
  64. #  Returns the minimum of all values passed in.                             #
  65. #                                                                           #
  66. #############################################################################
  67. sub min
  68. {
  69.     local( $result ) = pop( @_ );
  70.     foreach $item ( @_ )
  71.     {
  72.         $result = $item if $item < $result;
  73.     }
  74.     return( $result );
  75. }
  76.  
  77.  
  78. #############################################################################
  79. #                                                                           #
  80. #  Returns the absolute value of the number passed in.                      #
  81. #                                                                           #
  82. #############################################################################
  83. sub abs
  84. {
  85.     local( $result ) = $_[0];
  86.     $result *= -1 if $result < 0;
  87.     return( $result );
  88. }
  89.  
  90.  
  91. #############################################################################
  92. ###################################  INIT  ##################################
  93. #############################################################################
  94.  
  95.  
  96. #############################################################################
  97. # SET DEFAULT VARIABLE VALUES
  98.  
  99. $nLines = 0;    # Number of lines read from input file
  100.  
  101. $nVerts = 0;    # Number of verticies parsed out of the input file
  102. $nPolys = 0;    # Number of face-sets parsed out of the input file
  103. $nSNorms = 0;    # Number of surface-normals parsed out of the input file
  104. $nTNorms = 0;    # Number of texture-normals parsed out of the input file
  105.  
  106. $input_name = "STDIN";        # The input file name
  107. $output_name = "STDOUT";    # The output file name
  108. $verbose_name = "/dev/null";    # The verbose-message file name
  109.  
  110. $x_max = "";        # Max of all X-Coordinate vertex values
  111. $x_min = "";        # Min of all X-Coordinate vertex values
  112. $y_max = "";        # Max of all Y-Coordinate vertex values
  113. $y_min = "";        # Min of all Y-Coordinate vertex values
  114. $z_max = "";        # Max of all Z-Coordinate vertex values
  115. $z_min = "";        # Min of all Z-Coordinate vertex values
  116. $x_range = 0.0;        # MaxX - MinX
  117. $x_center = 0.0;    # (MaxX+MinX)/2
  118. $y_range = 0.0;        # MaxY - MinY
  119. $y_center = 0.0;    # (MaxY+MinY)/2
  120. $z_range = 0.0;        # MaxZ - MinZ
  121. $z_center = 0.0;    # (MaxZ+MinZ)/2
  122. $data_max = 0.0;    # MAX OF x_max, y_max, z_max
  123. $data_min = 0.0;    # MIN OF x_max, y_max, z_max
  124. $data_center = 0.0;
  125. $data_range = 0.0;
  126.  
  127. $normalize = 0;        # Should we normalize the data ? (default=NO)
  128. $x_scale = 1.0;        # Scale factor for X-Axis
  129. $y_scale = 1.0;        # Scale factor for Y-Axis
  130. $z_scale = 1.0;        # Scale factor for Z-Axis
  131. $colorize = 0;        # Should we color the data by depth ? (default=NO)
  132.  
  133.  
  134. #############################################################################
  135. # PARSE COMMAND LINE
  136.  
  137. while ( @ARGV )
  138. {
  139.     $option = shift( @ARGV );
  140.  
  141.     if ( $option eq "-infile" )
  142.     {
  143.         $input_name = shift( @ARGV );
  144.     }
  145.     elsif ( $option eq "-outfile" )
  146.     {
  147.         $output_name = shift( @ARGV );
  148.     }
  149.     elsif ( $option eq "-verbose" )
  150.     {
  151.         $verbose_name = "STDERR";
  152.     }
  153.     elsif ( $option eq "-normalize" )
  154.     {
  155.         $normalize = 1;
  156.     }
  157.     elsif ( $option eq "-colorize" )
  158.     {
  159.         $colorize = 1;
  160.     }
  161.     elsif ( $option eq "-xscale" )
  162.     {
  163.         $x_scale = shift( @ARGV );
  164.     }
  165.     elsif ( $option eq "-yscale" )
  166.     {
  167.         $y_scale = shift( @ARGV );
  168.     }
  169.     elsif ( $option eq "-zscale" )
  170.     {
  171.         $z_scale = shift( @ARGV );
  172.     }
  173.     elsif ( ! ( $option =~ /^-/ ) )
  174.     {
  175.         # Allow input and output file names to be specified
  176.         # without the lame option flags.  Just parse filenames out.
  177.         if ( $input_name eq "STDIN" )
  178.         {
  179.             if ( ! -f $option )
  180.             {
  181.                 print STDERR "Infile does not exist: $option\n";
  182.                 exit( 1 );
  183.             }
  184.             $input_name = $option;
  185.         }
  186.         elsif ( $output_name eq "STDOUT" )
  187.         {
  188.             $output_name = $option;
  189.         }
  190.         else
  191.         {
  192.             print STDERR "Too many files specified: $option\n";
  193.             exit( 1 );
  194.         }
  195.     }
  196.     else
  197.     {
  198.         print STDERR "Unknown option $option\n";
  199.         print STDERR "Usage: $0 [arguments]\n";
  200.         print STDERR "   [-infile inputfile]\n";
  201.         print STDERR "       default is STDIN\n";
  202.         print STDERR "   [-outfile outputfile]\n";
  203.         print STDERR "       default is STDOUT\n";
  204.         print STDERR "   -verbose\n";
  205.         print STDERR "       default is OFF\n";
  206.         print STDERR "   -normalize\n";
  207.         print STDERR "       default is OFF\n";
  208.         print STDERR "   -colorize\n";
  209.         print STDERR "       default is OFF\n";
  210.         print STDERR "   -xscale float\n";
  211.         print STDERR "       default is 1.0\n";
  212.         print STDERR "   -yscale float\n";
  213.         print STDERR "       default is 1.0\n";
  214.         print STDERR "   -zscale float\n";
  215.         print STDERR "       default is 1.0\n";
  216.         exit( 1 );
  217.     }
  218. }
  219.  
  220. if ( $input_name eq "STDIN" )
  221. {
  222.     open( INPUT, "<&STDIN" );
  223. }
  224. else
  225. {
  226.     open( INPUT, "<$input_name" );
  227. }
  228.  
  229. if ( $output_name eq "STDOUT" )
  230. {
  231.     open( OUTPUT, ">&STDOUT" );
  232. }
  233. else
  234. {
  235.     open( OUTPUT, ">$output_name" );
  236. }
  237.  
  238. if ( $verbose_name eq "STDERR" )
  239. {
  240.     open( VERBOSE, ">&STDERR" );
  241. }
  242. else
  243. {
  244.     open( VERBOSE, ">$verbose_name" );
  245. }
  246.  
  247. print VERBOSE "Using $input_name for input and $output_name for output...\n";
  248.  
  249.  
  250. #############################################################################
  251. ###################################  MAIN  ##################################
  252. #############################################################################
  253.  
  254.  
  255. #############################################################################
  256. # READ THE FILE INTO OUR "OBJ" LIST
  257.  
  258. print VERBOSE "Reading $input_name...  ";
  259.  
  260. @OBJ = <INPUT>;
  261. $nLines = $#OBJ + 1;
  262.  
  263. print VERBOSE "($nLines lines read)\n";
  264.  
  265. close( INPUT );
  266.  
  267.  
  268. #############################################################################
  269. # PARSE OUT: VERTICIES, POLYGONS, SURFACE NORMALS, AND TEXTURE NORMALS
  270.  
  271. print VERBOSE "Extracting data...\n";
  272.  
  273. for ( $i=0; $i<$nLines; $i++ )
  274. {
  275.     chop( $line = $OBJ[$i] );
  276.  
  277.     next if ( $line =~ /^#/ );  # Skip comments
  278.     next if ( $line =~ /^$/ );  # Skip blank lines
  279.  
  280.     if ( $line =~ /^v / )
  281.     {
  282.         ( $v, $x, $y, $z, @junk ) = split( /\s+/, $line );
  283.         $vertices{$nVerts} = join( " ", $x, $y, $z );
  284.  
  285.         if ( $x_max eq "" )
  286.         {
  287.             $x_max = $x;
  288.             $x_min = $x;
  289.             $y_max = $y;
  290.             $y_min = $y;
  291.             $z_max = $z;
  292.             $z_min = $z;
  293.         }
  294.         else
  295.         {
  296.             $x_max = &max( $x_max, $x );
  297.             $x_min = &min( $x_min, $x );
  298.             $y_max = &max( $y_max, $y );
  299.             $y_min = &min( $y_min, $y );
  300.             $z_max = &max( $z_max, $z );
  301.             $z_min = &min( $z_min, $z );
  302.         }
  303.  
  304.         $nVerts++;
  305.     }
  306.     elsif ( $line =~ /^f / )
  307.     {
  308.         @temp1 = split( /\s+/, $line );
  309.         shift( @temp1 );  # Toss the "f "
  310.         @temp2 = ();
  311.         for ( $j=0; $j<=$#temp1; $j++ )
  312.         {
  313.             ( $index, @junk ) = split( /\//, $temp1[$j] );
  314.             $index -= 1;
  315.             if ( $input_name =~ /eel/ ) { $index += 1; } # HACK
  316.             @temp2 = ( @temp2, $index );
  317.         }
  318.  
  319.         $connections{$nPolys} = join( " ", @temp2 );
  320.  
  321.         $nPolys++;
  322.     }
  323.     elsif ( $line =~ /^vt / )
  324.     {
  325.     }
  326.     elsif ( $line =~ /^vn / )
  327.     {
  328.     }
  329.     else
  330.     {
  331.     }
  332.  
  333. }
  334.  
  335. print VERBOSE "   Verticies: $nVerts\n";
  336. print VERBOSE "   Polygons:  $nPolys\n";
  337.  
  338. #############################################################################
  339. # CALCULATE DATA STATISTICS
  340.  
  341. print VERBOSE "Calculating data statistics...\n";
  342.  
  343. $x_range = &abs( $x_max - $x_min );
  344. $x_center = ($x_max + $x_min) / 2.0;
  345.  
  346. $y_range = &abs( $y_max - $y_min );
  347. $y_center = ($y_max + $y_min) / 2.0;
  348.  
  349. $z_range = &abs( $z_max - $z_min );
  350. $z_center = ($z_max + $z_min) / 2.0;
  351.  
  352. $data_max = &max( $x_max, $y_max, $z_max );
  353. $data_min = &min( $x_min, $y_min, $z_min );
  354. $data_center = ($data_max + $data_min) / 2.0;
  355. $data_range = &max( $x_range, $y_range, $z_range );
  356.  
  357. $normalization = $data_range / 2.0;
  358.  
  359. print VERBOSE "   x_max = $x_max\n";
  360. print VERBOSE "   x_min = $x_min\n";
  361. print VERBOSE "   x_center = $x_center\n";
  362. print VERBOSE "   x_range = $x_range\n";
  363. print VERBOSE "\n";
  364. print VERBOSE "   y_max = $y_max\n";
  365. print VERBOSE "   y_min = $y_min\n";
  366. print VERBOSE "   y_center = $y_center\n";
  367. print VERBOSE "   y_range = $y_range\n";
  368. print VERBOSE "\n";
  369. print VERBOSE "   z_max = $z_max\n";
  370. print VERBOSE "   z_min = $z_min\n";
  371. print VERBOSE "   z_center = $z_center\n";
  372. print VERBOSE "   z_range = $z_range\n";
  373. print VERBOSE "\n";
  374. print VERBOSE "   data_max = $data_max\n";
  375. print VERBOSE "   data_min = $data_min\n";
  376. print VERBOSE "   data_center = $data_center\n";
  377. print VERBOSE "   data_range = $data_range\n";
  378. print VERBOSE "Done calculating data statistics.\n";
  379.  
  380. #############################################################################
  381. # WRITE VRML
  382.  
  383. print VERBOSE "Writting $output_name...\n";
  384.  
  385. print OUTPUT "#VRML V1.0 ascii\n";
  386. print OUTPUT "\n";
  387. print OUTPUT "Separator {\n";
  388.  
  389. print OUTPUT "\tSeparator {\n";
  390. print OUTPUT "\t\tTransform { rotation -1 0 0 3.0 }\n";
  391. # print OUTPUT "\t\tLightModel { model BASE_COLOR }\n";
  392.  
  393. if ( $colorize )
  394. {
  395.     print OUTPUT "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n";
  396.  
  397.     #####################################################################
  398.     # WRITE MATERIAL TABLE
  399.  
  400.     print OUTPUT "\t\tMaterial {\n";
  401.     print OUTPUT "\t\t\tdiffuseColor [\n";
  402.  
  403.     for ( $i=0; $i<$nVerts; $i++ )
  404.     {
  405.         # DEREFERENCE A VERTICY
  406.  
  407.         @vert = split( /\s+/, $vertices{$i} );
  408.  
  409.         # COLORIZE THE DATA
  410.         if ( $z_range != 0 ) { $vert[2] /= ($z_range / 2.0); }
  411.         $red = 0.0;
  412.         $green = 1.0-$vert[2]/-1.5;
  413.         $blue = 0.5+$vert[2]/-1.5;
  414.  
  415.         if ( $vert[2] == 0.0 )
  416.         {
  417.             $red = 0.0;
  418.             $green = 0.25;
  419.             $blue = 0.0;
  420.         }
  421.  
  422.         # OUTPUT THE DATA
  423.  
  424.         print OUTPUT "\t\t\t\t";
  425.         printf( OUTPUT "%f %f %f", $red, $green, $blue );
  426.         if ( $i == $nVerts - 1 )
  427.         {
  428.             print OUTPUT "\n";
  429.         } else {
  430.             print OUTPUT ",\n";
  431.         }
  432.     }
  433.     printf OUTPUT "\t\t\t]\n";
  434.     printf OUTPUT "\t\t}\n";
  435. }
  436.  
  437. #############################################################################
  438. # WRITE VERTEXT DATA
  439.  
  440. print OUTPUT "\t\tCoordinate3 {\n";
  441. print OUTPUT "\t\t\tpoint [\n";
  442.  
  443. for ( $i=0; $i<$nVerts; $i++ )
  444. {
  445.     # DEREFERENCE A VERTICY
  446.  
  447.     @vert = split( /\s+/, $vertices{$i} );
  448.  
  449.     if ( $normalize == 1 )
  450.     {
  451.         # CENTER THE DATA
  452.         $vert[0] -= $x_center;
  453.         $vert[1] -= $y_center;
  454.         $vert[2] -= $z_center;
  455.  
  456.         # NORMALIZE THE DATA
  457.         $vert[0] /= $normalization;
  458.         $vert[1] /= $normalization;
  459.         $vert[2] /= $normalization;
  460.     }
  461.  
  462.     # SCALE THE DATA
  463.     if ( $x_scale != 1.0 ) { $vert[0] *= $x_scale; }
  464.     if ( $y_scale != 1.0 ) { $vert[1] *= $y_scale; }
  465.     if ( $z_scale != 1.0 ) { $vert[2] *= $z_scale; }
  466.  
  467.     # OUTPUT THE DATA
  468.  
  469.     print OUTPUT "\t\t\t\t";
  470.     printf( OUTPUT "%f %f %f", $vert[0], $vert[1], $vert[2] );
  471.     if ( $i == $nVerts - 1 )
  472.     {
  473.         print OUTPUT "\n";
  474.     } else {
  475.         print OUTPUT ",\n";
  476.     }
  477. }
  478. printf OUTPUT "\t\t\t]\n";
  479. printf OUTPUT "\t\t}\n";
  480.  
  481. #############################################################################
  482. # WRITE CONNECTIVITY DATA
  483.  
  484. print OUTPUT "\t\tIndexedFaceSet {\n";
  485. print OUTPUT "\t\t\tcoordIndex [\n";
  486.  
  487. for ( $i=0; $i<$nPolys; $i++ )
  488. {
  489.     # EXTRACT THE NEXT SET OF VERTICIES FOR A NEW QUAD
  490.  
  491.     @cons = split( /\s+/, $connections{$i} );
  492.  
  493.     print OUTPUT "\t\t\t\t";
  494.  
  495.     for ( $j=0; $j<=$#cons; $j++ )
  496.     {
  497.         # $cons[$j] -= 1;  ALREADY DONE IN EXTRACTION STEP
  498.         print OUTPUT "$cons[$j], ";
  499.     }
  500.     print OUTPUT "-1";
  501.  
  502.     if ( $i == $nPolys - 1 )
  503.     {
  504.         print OUTPUT "\n";
  505.     } else {
  506.         print OUTPUT ",\n";
  507.     }
  508.  
  509. }
  510.  
  511. print OUTPUT "\t\t\t]\n";
  512. print OUTPUT "\t\t}\n";
  513. print OUTPUT "\t}\n";
  514.  
  515. #############################################################################
  516. # DONE
  517.  
  518. print OUTPUT "}\n";
  519.  
  520. close( OUTPUT );
  521.  
  522. print VERBOSE "Done writting $output_name...\n";
  523.  
  524. print VERBOSE "Done\n";
  525.  
  526.